/*
 * ============================================================================
 *                   GNU Lesser General Public License
 * ============================================================================
 *
 *
 *
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
 *
 *
 *
 */
package rad.framework.richfaces;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.richfaces.event.NodeSelectedEvent;
import org.richfaces.model.TreeNode;

/**
 * @author boudyacho
 */
public abstract class BaseTreeNode implements TreeNode {

	protected static final Log log = LogFactory.getLog(BaseTreeNode.class);

	private static final long serialVersionUID = 1L;

	private TreeNode<?> parent;

	protected Map<Object, BaseTreeNode> children = new TreeMap<Object, BaseTreeNode>();

	public BaseTreeNode(TreeNode<?> parent) {
		this.parent = parent;
	}
	
	//---------------------------------------

	abstract public String getType();

	abstract public String getIcon();

	abstract public String getText();

	abstract public Object getKey();

	public String getViewPath() {
		return "";
	}

	//---------------------------------------

	public Object getData() {
		return this;
	}

	public void setData(Object arg0) {
	}

	public TreeNode<?> getParent() {
		return parent;
	}

	public void setParent(TreeNode parent) {
		this.parent = parent;
	}

	public boolean isLeaf() {
		return getChildCount() == 0;
	}

	//---------------------------------------

	private RootTreeNode root = null;
	
	public RootTreeNode getRoot() {
		if (root == null) {
			BaseTreeNode parent = (BaseTreeNode) getParent();
			if (parent != null) {
				root = parent.getRoot();
				return root;
			}
			throw new RuntimeException("Parent should not be null for: "
					+ getText());
		}
		return root;
	}

	//---------------------------------------

	public void addChild(Object id, TreeNode child) {
		if (id == null) {
			id = new Long(-1);
		}
		children.put(id, (BaseTreeNode) child);
	}

	public void removeChild(Object id) {
		if (id == null)
			return;
		Object kid = children.remove(id);
		if (kid instanceof EntityTreeNode) {
			getRoot().remove(((EntityTreeNode<?>)kid));
		}
	}

	public TreeNode<?> getChild(Object id) {
		if (id == null)
			return null;
		return children.get(id);
	}

	@SuppressWarnings("unchecked")
	public Iterator getChildren() {
		if (children.size() == 0) {
			initializeChildren();
		}
		return children.entrySet().iterator();
	}

	protected void initializeChildren() {
		// the order of children is controlled by the key in the map entry
	}

	public void clearChildren() {
//		children.clear();
	}
	
	public int getChildCount() {
		getChildren();
		return children.size();
	}

	public List<TreeNode> getChildrenList() {
		getChildren();
		return new ArrayList<TreeNode>(children.values());
	}

	public void setChildrenList(List<TreeNode> list) {
	}

	public List<TreeNode> getChildList() {
		return new ArrayList<TreeNode>(children.values());
	}
	
	//---------------------------------------
	// Crumbs
	
	public List<BaseTreeNode> getParentTree() {
		return getParentTreeNodes(new ArrayList<BaseTreeNode>());
	}

	public List<BaseTreeNode> getParentTreeNodes(ArrayList<BaseTreeNode> tree) {
		return tree;
	}

	//---------------------------------------

	public String changeCurrent(NodeSelectedEvent event) {
		setCurrent(this);
		return null;
	}

	public void setCurrent(BaseTreeNode current) {
		getRoot().setCurrent(current);
	}

	public boolean isCurrentNode() {
		RootTreeNode root = getRoot();
		BaseTreeNode current = root.getCurrent();
		return this.equals(current);
	}

	public boolean isMasterNode() {
		RootTreeNode root = getRoot();
		BaseTreeNode master = root.getMaster();
		return this.equals(master);
	}

	//---------------------------------------
	
	/**
	 * called by edit-template.xhtml
	 * false for root and true for folder
	 */
	public boolean isRenderSiblings() {
		return false;
	}
}
